// function getVal(name:string):string{
//     return name
// }
// function getVal(name:number|string):number|string{
//     return name
// }
// getVal('dfghj')



// function getVal(name:any):any{  // 都用any的话，失去了 ts 本身的意思
//    return name
// }
// 向上面的函数，没有办法保证，传入的类型和返回的类型的一致性；

// 向上面的这种用法，就会显得代码，比较死板，没有灵活性。



// 泛型 T 指的是类型，并不是值

// function getVal<T>(name:T):T{
//     return name
// }

// // let v = getVal('王麻子');
// // let a = getVal(23);

// let v = getVal<string>('王麻子');

// let a = getVal<number>(23);




// let arr:[string, number] = ['a', 1];

// T 和 U 就是代表 类型的变量 （T,U）可以改成你想改写的任何的字母
// 但是，我们习惯上 使用 T,U 来进行表示
// function reverseArr<A, B>(arr: [A, B]): [B, A] {
//     return [arr[1], arr[0]]
// }

// let arr1:[number, string] = [12,'b'];

// function reverseArr<T, U>(arr: [T, U]): [U, T] {
//     return [arr[1], arr[0]]
// }
// console.log(reverseArr(arr1));



class minClass<T> {
    public list:T[] = []
    add(val:T):void{
        this.list.push(val)
    }
    min():T{
        // let _min = this.list[0]
        // for(let i=0;i<this.list.length;i++){
        //     if(_min > this.list[i]){
        //         _min = this.list[i]
        //     }
        // }
        // return _min
        return <any>Math.min(...<any>this.list);

    }
}

let m = new minClass<number>() // 实例化类 并且制定了类的T代表是 number
m.add(1);  m.add(2); m.add(0); m.add(4); m.add(5);

console.log(m.min());



// interface Ilength {
//     length: number
// }

// function getLength<T extends Ilength>(val: T): number {
//     return val.length
// }

// // getLength(1) // 错误的写法

// getLength([1,2,3,4])

// getLength('str')

// getLength([])

// getLength({ length: 0 })


interface Iadd { // 接口里面所有的参数和函数的返回值，必须一致
    <T>(x:T,y:T):T
}


let add:Iadd = <T>(x:T,y:T):T=>{
   
    return <any>x + y
}
console.log(add(10,20));
